Django Forms を使ってみよう
Django Formでフォームを作成
機能盛りだくさんの Django には、HTMLフォームを生成するための Django Forms があります。アプリケーション authdemoを作成して、 forms.py を作成して、フォームを定義してみましょう。
code: bash
$ python manage.py startapp authdemo
$ mkdir authdemo/templates
アプリケーションを登録
プロジェクトのsetting.py で INSTALLED_APPS=[] に authdemo を追加します。
code: python settings.py からの抜粋
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hello',
'authdemo',
]
プロジェクトの urls.py に authdemo のURLを登録します。
code: Python
# ...
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
path('authdemo/', include('authdemo.urls')),
]
フォームの作成
code: authdemo/forms.py
from django import forms
class UserForm(forms.Form):
username = forms.CharField(label='Username', max_length=32)
password = forms.CharField(label='Password',
min_length=8, max_length=32,
widget=forms.PasswordInput)
ここでは、CharField() しか使っていませんが、Django Froms では様々なフィールドタイプとバリデータを使用することができます。(詳しくは後述します)
フォームオブジェクトをrender()に渡す
ビュー関数login()を作成し、そこで render() にフォームオブジェクトを渡します。
code: authdemo/views.py
from .forms import UserForm
# ...
def login(request):
values = {'form': UserForm()}
return render(request, 'login.html', values)
render() には辞書型オブジェクトしか与えることができないことを思い出してください。
キー'form' のアイテムとして formオブジェクトを与えています。
URLパターンに登録します。
code: authdemo/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('index/', views.index, name='index'),
path('artist_list/', views.artist_list, name='artist_list'),
path('login/', views.login, name='login'),
]
テンプレートを用意しましょう。
まず、ベーステンプレートです。
code: authdemo/templates/base.hml
<html>
<head>
{% if title %}
<title>{{ title }} - Django Example </title>
{% else %}
<title>Django Example</title>
{% endif %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
login.html をbase.html のチャイルド・テンプレートとして定義します。
code: authdemo/templates/login.html
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
{% endblock %}
このテンプレートの要点はつぎのようになります。
CSRF攻撃から保護するための {% csrf_token %} がある
フィールドごとではなく {{ form }} で一括してレンダリングさせている
フィールドタイプにSumitボタンがないので、INPUTタグを使って記述している
https://gyazo.com/242d101f851e7266ed845999436ceb7e
formオブジェクト全体をレンダリングさせると、横並びになってしまいます。
フィールドごとにレンダリングさせたいときは、formオブジェクトのレンダリングオプションを指示して行います。
code: authdemo/templates/login.html
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}
https://gyazo.com/efa7fae01f5c1f620f87829d98ac5af9
フォームのレンダリングオプションには次の指定ができます。
{{ form.as_table }}: <tr>タグを使ってテーブルとして表示
{{ form.as_p }}:<p>タグを使って表示
{{ form.as_ul }}:<li> タグを使って表示
Django Forms のフィールドタイプとバリデータ
table: Django Fromsのフィールド対応
フィールドタイプ 説明
BooleanField True/False のブール値をもつチェックボックス
CharField テキスト入力
ChoiceField 選択肢をリストするドロップダウンフィールド
TypedChoiceField 選択肢をリストするドロップダウンフィールド
coerceで型を指定
DateField 特定の形式で日付(datetime.date値)を入力するフィールド
DateTimeField 特定の形式で日時(datetime.datetime値)を入力するフィールド
DecimalField 10進数を入力するテキストフィールド
DurationField 特定の形式で日時差(Timedelta値)を入力するフィールド
EmailField Eメールを入力するフィールド
FileField ファイルのアップロードフィールド
FilePathField 特定のディレクトリにあるファイルを指定するフィールド
FloatField 浮動小数点値を入力するテキストフィールド
ImageField 画像ファイルのアップロードフィールド
Pillowモジュールが必要
IntegerField 整数値を入力するテキストフィールド
GenericIPAddressField IPアドレスを入力するテキストフィールド
MultipleChoiceField 選択肢を複数選択可能なドロップダウンフィールド
TypedMultipleChoiceField 複数選択可能な選択肢をリストするドロップダウンフィールド
coerceで型を指定
NullBooleanField Nullが可能なBooleanField
RegexField データに正規表現を適用した結果を返すテキストフィールド
SlugField スラッグIDを入力するテキストフィールド
TimeField 特定の形式で時刻(datetime.time値)を返すテキストフィールド
URLField URLを入力するテキストフィールド
UUIDField UUIDを入力するテキストフィールド
ComboField 複数のフィールドをまとめるフォームフィールド
MultiValueField ひとつの入力フィールドで複数の値を受け入れることができる
SplitDateTimeField 特定の形式で日時を入力するフィールド
日付(datetime.date値)と時刻(datetime.datetime値)を返す
ModelChoiceField 選択肢をデータベースから読み出すドロップダウンフィールド
ModelMultipleChoiceField 複数選択可能な選択肢をリストするドロップダウンフィールド
選択肢はデータベースから読み出す
table: Django Formsのバリデータ
バリデータ 説明
RegexValidator 正規表現パターンに合致するデータかどうかを検証する
validate_email Emailアドレスとしての妥当性を検証する
validate_slug スラッグIDとしての妥当性を検証する
validate_unicode_slug スラッグIDとしての妥当性を検証する
validate_ipv4_address IPv4アドレスとしての妥当性を検証する
validate_ipv6_address IPv6アドレスとしての妥当性を検証する
validate_ipv46_address IPアドレスとしての妥当性を検証する
validate_comma_separated_integer_list カンマで区切られた整数値のリストかどうかを検証する
int_list_validator 整数値のリストかどうかを検証する
MaxValueValidator データが指定した最大値を超えていないか検証する
MinValueValidator データが指定した最小値より小さくないか検証する
MaxLengthValidator データの長さが指定した値を超えていないか検証する
MinLengthValidator データの長さが指定した値以上あるか検証する
DecimalValidator 10進整数かどうかを検証する
FileExtensionValidator ファイルの拡張子が与えたものに合致するか検証する
validate_image_file_extension 画像ファイルの拡張子かどうかを検証する
ProhibitNullCharactersValidator NULL文字を禁止する
モデルフォーム
これまで、 Django Formsの使い方を説明することを目的ににしてきたため、Django Modelでデータベースのモデルを作成してきませんでした。
しかし、データベース駆動型アプリケーションの場合は、モデルに密接に対応するフォームが作成されることが多くなります。 例えば、ログイン認証でユーザ登録や登録情報の修正のために、Django Model としてUserモデルとユーザ登録用フォームを作るときを考えてみましょう。モデルでフィールドを定義することになるため、フォームでフィールドタイプを改めて定義することは冗長になってしまいます。
こうしたときのために、Djangoには、django.forms.ModelForm と言う Modelクラスを元にフォームを自動生成してくれるクラスが用意されています。
Userモデルの作成
Django には 、デフォルトでUserモデルが存在していて、django.contrib.auth にユーザ認証用の事前に定義されているクラスやツールセットもあります。しかし、ここでは説明を簡単にして理解をすることに重点をおくためにあえて使わないようにします。
まず、フォームの作成ために作ったアプリケーション authdemo にユーザ登録のためのUserモデルを作成しましょう。
code: models.py
from django.db import models
class User(models.Model):
id = models.IntegerField(primary_key=True)
username = models.CharField(max_length=16)
email = models.EmailField(max_length = 254)
password = models.CharField(max_length=128)
詳しくは後述していますが、フォームでフィールドタイプを指定するように、モデルにもフィールドタイプがあり、これを使ってデータベースのテーブルのモデル User を作成しています。
フォームは次のように作成します。
code: forms.py
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', 'password')
widgets = {'password': forms.PasswordInput()}
froms.ModelForm を継承したUserFormクラスを作成します。ここでは、モデルにUserを指定しています。データベーステーブルのフィールドのうち一部からフォームを作成するときは、fields にタプルで指定します。
django を起動して動作確認してみます。
code:bash
$ python manage.py runserver
テンプレート
https://gyazo.com/6620dca689d22c27998d3f652bd33568
ModelFom と Form のフィールドタイプの対応
table: ModelForm フィールドと Formフィールドの対応
Model フィールド Form フィールド
AutoField Formにはありません
BigAutoField Formにはありません
BigIntegerField IntegerField (-9223372036854775808〜9223372036854775807)
BinaryField CharField (ModelFromのフィールドが編集可能に設定されているとき)
BooleanField BooleanField、NullBooleanField(null=Trueのとき)
CharField CharField
DateField DateField
DateTimeField DateTimeField
DecimalField DecimalField
DurationField DurationField
EmailField EmailField
FileField FileField
FilePathField FilePathField
FloatField FloatField
ForeignKey ModelChoiceField
ImageField ImageField
IntegerField IntegerField
IPAddressField IPAddressField
GenericIPAddressField GenericIPAddressField
ManyToManyField ModelMultipleChoiceField
NullBooleanField NullBooleanField
PositiveIntegerField IntegerField
PositiveSmallIntegerField IntegerField
SlugField SlugField
SmallAutoField Formにはありません
SmallIntegerField IntegerField
TextField CharField (widget=forms.Textareaのとき)
TimeField TimeField
URLField URLField
UUIDField UUIDField
ユーザ認証について
実は、Django には管理画面があり、ここでユーザ認証しているため、既にUserモデルは実装されています。
多くの場合、次の2つのモジュールを使用してUserモデルを継承してカスタマイズします。
django.contrib.auth.models.AbstractUser
簡単に継承できるけれど、自由度がすくない
django.contrib.auth.base_user.AbstractBaseUser
継承するためには制約や手間が必要だけれど、自由度が高い
この資料では Django Forms を説明するためのUserモデルを実装しました。
詳しくは公式ドキュメントを参照してください。
参考: